package cn.py.boot_lua.service;

import cn.py.boot_lua.dto.SeckillResult;
import cn.py.boot_lua.util.LuaScriptLoader;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SeckillService {

    private final RedissonClient redissonClient;
    private final StringRedisTemplate redisTemplate;
    private final LuaScriptLoader luaScriptLoader;
    private ThreadPoolTaskExecutor executor;

    public SeckillService(RedissonClient redissonClient,
                          StringRedisTemplate redisTemplate,
                          LuaScriptLoader luaScriptLoader,
                          @Qualifier("defaultThreadPoolTaskExecutor") ThreadPoolTaskExecutor executor) {
        this.redissonClient = redissonClient;
        this.redisTemplate = redisTemplate;
        this.luaScriptLoader = luaScriptLoader;
        this.executor = executor;
    }
    /**
     * @param productId 产品id
     * @param userId 用户id
     */
    public int seckill(String productId, String userId) {
        String stockKey = "seckill:product:" + productId + ":stock";  // 存储该商品剩余库存的 Redis 键
        String userSetKey = "seckill:product:" + productId + ":users"; // 存储已成功抢购该商品的用户集合的 Redis 键

        RLock lock = redissonClient.getLock("lock:seckill:" + productId);
        try {
            // 获取分布式锁，最多等待 3s，持有 10s
            if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
                List<String> keys = Arrays.asList(stockKey, userSetKey);

                DefaultRedisScript<Long> script = new DefaultRedisScript<>();
                script.setScriptText(luaScriptLoader.getSeckillScript());
                script.setResultType(Long.class);

                Long result = redisTemplate.execute(script, keys, userId);
                return result != null ? result.intValue() : -1;
            } else {
                return -3; // 获取锁失败
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -4;
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }


    public List<String> TaskExecutor(List<String> list){
        List<CompletableFuture<String>> futures = new ArrayList<>();
        for (int i = 0; i < list.size(); i++){
            String file = list.get(i);
            CompletableFuture<String> exceptionally = CompletableFuture.supplyAsync(() -> this.filesMusicPath(file), executor)
                    .exceptionally(ex -> {
                        log.error("异步调用发生异常： " + file + ": " + ex.getMessage());
                        return "";
                    });
            futures.add(exceptionally);
        }
        List<String> lists = new ArrayList<>();
        try {
            // 等待所有异步任务完成
            CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allOf.get(300, TimeUnit.SECONDS);
            // 收集所有任务的结果
            lists = futures.stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("异步调用发生异常：", e);
            throw new RuntimeException(e.getMessage());
        }
        return lists;
    }
    public String filesMusicPath(String pool){
        return pool;
    }


    public void TaskExecutorVoid(List<String> list){
        for (String file : list) {
            CompletableFuture.runAsync(() -> {
                try {
                    filest(file);
                } catch (Exception ex) {
                    log.error("异步调用发生异常：{}", file, ex);
                }
            }, executor);
        }
    }
    public String filest(String pool){
        return pool;
    }

}
